package com.example.base_model.ext

import com.example.base_model.network.request_param.RequestParamInterface

/**
 * @Author jiangKunKun
 * @CreateDate 2025/7/15
 * @Description 为 [RequestParamInterface] 提供扩展函数，以安全、便捷地将其内部的原始参数 ([getRawParam]) 转换为特定类型。
 * @SpittingGrooves
 */

/**
 * 安全地将原始参数转换为指定的类型 `T`。
 *
 * 此函数利用 reified 泛型，在运行时检查原始参数的类型是否与 `T` 匹配。
 * 如果类型匹配，则执行给定的 `block`，并将转换后的参数传递给它。
 *
 * @param T 目标类型。
 * @param block 如果类型转换成功，将以转换后的对象为参数来执行此代码块。
 *
 * @receiver RequestParamInterface
 *
 * **用法示例:**
 * ```
 * requestParam.castTo<User> { user ->
 *     // 在这里使用 user 对象
 *     println("User name: ${user.name}")
 * }
 * ```
 */
inline fun <reified T> RequestParamInterface.castTo(crossinline block: (T) -> Unit) {
    // 1. 获取接口中存储的原始参数
    val raw = getRawParam()
    // 2. 由于 T 是 reified，我们可以直接在运行时检查 `raw` 是否是 T 的实例
    if (raw is T) {
        // 3. 如果类型匹配，则调用 lambda 并将安全转换后的 `raw` 传递给它
        block(raw)
    }
}

/**
 * 尝试将原始参数转换为 `List<T>`。
 *
 * **警告**: 此函数存在局限性。由于 JVM 的类型擦除，无法在运行时直接检查一个 `List` 的泛型类型是否为 `T`。
 * 作为一种变通方法，此函数会检查：
 * 1. 原始参数是否是一个 `List<*>`。
 * 2. 列表是否非空。
 * 3. 列表的**第一个元素**是否是 `T` 的实例。
 *
 * 只有当所有条件都满足时，它才会执行一个 **"UNCHECKED_CAST"**（未检查的转换）。
 * 这意味着，如果列表包含不同类型的元素，在后续操作中仍可能发生 [ClassCastException]。
 *
 * @param T 列表中元素的目标类型。
 * @param block 如果转换被认为“可能安全”，将以转换后的列表为参数来执行此代码块。
 *
 * @receiver RequestParamInterface
 *
 * **用法示例:**
 * ```
 * requestParam.castToListOf<Product> { productList ->
 *     productList.forEach { product ->
 *         println("Product: ${product.name}")
 *     }
 * }
 * ```
 */
inline fun <reified T> RequestParamInterface.castToListOf(crossinline block: (List<T>) -> Unit) {
    val raw = getRawParam()
    // 检查原始值是否为 List
    if (raw is List<*>) {
        // 由于类型擦除，只能通过检查第一个元素来猜测列表类型
        if (raw.isNotEmpty() && raw.first() is T) {
            // 这是一个未检查的转换，因为我们只验证了第一个元素
            @Suppress("UNCHECKED_CAST")
            block(raw as List<T>)
        }
    }
}

/**
 * 尝试将原始参数转换为 `Map<String, Any>`。
 *
 * **警告**: 此函数执行 **"UNCHECKED_CAST"**（未检查的转换）。
 * 它只检查原始参数是否为 `Map<*, *>`，但无法在运行时保证其键是 `String` 类型，值是 `Any` 类型。
 * 如果映射包含非字符串键，在后续操作中可能会导致 [ClassCastException]。
 *
 * @param block 如果原始参数是一个 Map，将以转换后的 Map 为参数来执行此代码块。
 *
 * @receiver RequestParamInterface
 *
 * **用法示例:**
 * ```
 * requestParam.castToMap { dataMap ->
 *     val username = dataMap["username"] as? String
 *     println("Username from map: $username")
 * }
 * ```
 */
fun RequestParamInterface.castToMap(block: (Map<String, Any>) -> Unit) {
    val raw = getRawParam()
    // 检查原始值是否为 Map
    if (raw is Map<*, *>) {
        // 这是一个未检查的转换，因为我们无法保证键和值的具体类型
        @Suppress("UNCHECKED_CAST")
        block(raw as Map<String, Any>)
    }
}
